<template>
  <div class="flex flex-col h-full !rounded-tl-16px !rounded-tr-16px">
    <div class="b-1 b-[var(--el-border-color)] b-b-none">
      <div class="pl28px pt-10px text-#696969 text-16px pb-16px">音乐任务</div>
      <transition name="fade">
        <div v-if="currentSong.id" class="flex-1 flex items-center justify-center mb-20px">
          <audioBar ref="audioBarRef" class="min-w-750px" :song="currentSong" />
        </div>
      </transition>
    </div>

    <div class="flex-auto flex overflow-hidden">
      <view class="w-100% flex flex-col overflow-hidden">
        <div class="flex-1 flex overflow-hidden mb-20px">
          <el-scrollbar height="100%" class="w-full">
            <div class="music-list-scroll pl-28px">
              <div v-if="musicList.length" :gutter="12" class="flex flex-wrap gap-20px">
                <div v-for="song in musicList" :key="song.id" :span="8" class="w-444px">
                  <songCard
                    :songInfo="song"
                    @play="setCurrentSong(song)"
                    @delete="deleteSong(song)"
                    @download="downloadSong(song)"
                    :loading="inProgressMusicMap[song.id]?.status === AiMusicStatusEnum.IN_PROGRESS"
                  />
                </div>
              </div>
              <el-empty v-else description="暂无音乐" />
            </div>
          </el-scrollbar>
          <!-- songInfo -->
          <songInfo class="flex-none" :song="currentSong" />
        </div>

        <div class="b-1 b-[var(--el-border-color)] b-t-none p-r-20px">
          <Pagination
            :pageSizes="[12, 20, 30, 50, 100]"
            :total="pageTotal"
            v-model:page="queryParams.pageNo"
            v-model:limit="queryParams.pageSize"
            @pagination="getMusicList()"
          />
        </div>
      </view>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { MusicApi, MusicVO } from '@/api/ai/music'
import songCard from './songCard/index.vue'
import songInfo from './songInfo/index.vue'
import audioBar from './audioBar/index.vue'
import { ElLoading, LoadingOptionsResolved } from 'element-plus'
import { AiMusicStatusEnum } from '@/views/ai/utils/constants'
import download from '@/utils/download'
// 导入音乐风格图片
import HappyImg from '@/assets/ai/music/快乐.jpg'
import DynamicImg from '@/assets/ai/music/活力.jpg'
import SentimentalImg from '@/assets/ai/music/EMO.jpg'
import InspirationalImg from '@/assets/ai/music/鼓舞.jpg'
import NostalgicImg from '@/assets/ai/music/怀旧.jpg'
import ExcitedImg from '@/assets/ai/music/兴奋.jpg'
import SorrowImg from '@/assets/ai/music/伤感.jpg'
import ChillImg from '@/assets/ai/music/放松.jpg'
import RomanticImg from '@/assets/ai/music/浪漫.jpg'
import MissImg from '@/assets/ai/music/思念.jpg'
import GroovyImg from '@/assets/ai/music/律动.jpg'
import DreamyImg from '@/assets/ai/music/梦幻.jpg'
import CalmImg from '@/assets/ai/music/平静.jpg'

defineOptions({ name: 'Index' })
const message = useMessage() // 消息弹窗
// 当前音乐
const currentSong: any = ref({})

// 音乐风格图片映射
const moodImageMap = {
  Happy: HappyImg,
  'Dynamic/Energetic': DynamicImg,
  'Sentimental/Melancholic/Lonely': SentimentalImg,
  'Inspirational/Hopeful': InspirationalImg,
  'Nostalgic/Memory': NostalgicImg,
  Excited: ExcitedImg,
  'Sorrow/Sad': SorrowImg,
  Chill: ChillImg,
  Romantic: RomanticImg,
  Miss: MissImg,
  'Groovy/Funky': GroovyImg,
  'Dreamy/Ethereal': DreamyImg,
  'Calm/Relaxing': CalmImg
}

// 所有音乐风格图片数组，用于随机选择
const moodImages = Object.values(moodImageMap)

// 视频分页相关的参数
const queryParams = reactive({
  pageNo: 1,
  pageSize: 12
})
const pageTotal = ref<number>(0) // page size
const musicList = ref<MusicVO[]>([]) // music 列表
const musicListLoadingInstance = ref<any>() // music 列表是否正在加载中
const musicListRef = ref<any>() // ref
// 视频轮询相关的参数（正在生成中的）
const inProgressMusicMap = ref<{}>({}) // 监听的 music 映射，一般是生成中（需要轮询），key 为 music 编号，value 为 music
const inProgressTimer = ref<any>() // 生成中的 music 定时器，轮询生成进展
const audioBarRef = ref<any>()
provide('currentSong', currentSong)

// 设置音乐图片
const setMusicImage = (music: any) => {
  if (!music.imageUrl && music.status === AiMusicStatusEnum.SUCCESS) {
    if (music.moodSong && moodImageMap[music.moodSong]) {
      music.imageUrl = moodImageMap[music.moodSong]
    } else {
      // 随机选择一张图片
      const randomIndex = Math.floor(Math.random() * moodImages.length)
      music.imageUrl = moodImages[randomIndex]
    }
  }
}
const getMusicList = async (isInit = false) => {
  try {
    if (isInit) {
      queryParams.pageNo = 1
    }
    // 1. 加载视频列表
    musicListLoadingInstance.value = ElLoading.service({
      target: musicListRef.value,
      text: '加载中...'
    } as LoadingOptionsResolved)
    const { list, total } = await MusicApi.getMusicMyPage(queryParams)

    // 处理音乐列表中的图片
    musicList.value = list.map((song) => {
      setMusicImage(song)
      return song
    })

    pageTotal.value = total

    // 2. 计算需要轮询的视频
    const newWatMusics = {}
    musicList.value.forEach((item) => {
      if (item.status === AiMusicStatusEnum.IN_PROGRESS) {
        newWatMusics[item.id] = item
      }
    })
    inProgressMusicMap.value = newWatMusics
  } finally {
    // 关闭正在“加载中”的 Loading
    if (musicListLoadingInstance.value) {
      musicListLoadingInstance.value.close()
      musicListLoadingInstance.value = null
    }
  }
}
/** 轮询生成中的 music 列表 */
const refreshWatchMusics = async () => {
  const musicIds = Object.keys(inProgressMusicMap.value).map(Number)
  if (musicIds.length == 0) {
    return
  }
  const list = await MusicApi.getMusicListMyByIds(musicIds)
  const newWatchMusics = {}
  list?.forEach((music) => {
    // 处理音乐图片
    setMusicImage(music)
    if (music.status === AiMusicStatusEnum.IN_PROGRESS) {
      newWatchMusics[music.id] = music
    } else {
      const index = musicList.value.findIndex((oldMusic) => music.id === oldMusic.id)
      if (index >= 0) {
        // 更新 musicList
        musicList.value[index] = music
      }
    }
  })
  inProgressMusicMap.value = newWatchMusics
}
/*
 *@Description: 设置当前播放的音乐
 *@MethodAuthor: xiaohong
 *@Date: 2024-07-19 11:22:33
 */
function setCurrentSong(music: Recordable) {
  if (currentSong.value?.id === music.id) {
    audioBarRef.value?.togglePlay?.()
    return
  }
  currentSong.value = music
}
const deleteSong = async (song: Recordable) => {
  // TODO: 调用删除接口并刷新列表
  await message.confirm(`是否删除该音乐?`)
  await MusicApi.deleteMusic(song.id)
  await getMusicList()
  message.success('删除成功!')
}
function downloadSong(song: Recordable) {
  // TODO: 下载逻辑)
  download.file(song.audioUrl || song.musicUrl)
}
// 组件挂在的时候
onMounted(async () => {
  // 获取 music 列表
  await getMusicList()
  // 自动刷新 music 列表
  inProgressTimer.value = setInterval(async () => {
    await refreshWatchMusics()
  }, 1000 * 3)
})
onUnmounted(() => {
  // 清除定时器
  if (inProgressTimer.value) {
    clearInterval(inProgressTimer.value)
    inProgressTimer.value = null
  }
})
defineExpose({
  getMusicList
})
</script>

<style lang="scss" scoped>
@import url('@/views/ai/image/index/components/index.scss');

.music-list-scroll {
  flex: 1;
  padding-right: 8px;
  overflow-y: auto;
}

.task-music-pagination {
  padding: 0 20px;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>
